package com.lc.admin.interceptor;

import cn.hutool.core.text.AntPathMatcher;
import com.alibaba.fastjson.JSONObject;
import com.lc.admin.bean.LoginUserDetails;
import com.lc.admin.constants.RedisKeyConstants;
import com.lc.admin.utils.JwtUtil;
import com.lc.admin.utils.StringUtils;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * 认证管理器
 */
@Component
public class TokenAuthrizationManager implements AuthorizationManager<RequestAuthorizationContext> {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Value("${zhyl.securet}")
    private String secret;

    @Value("${zhyl.expire}")
    private Integer expire;

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext request) {
        // 获取uuid
        String uuid = request.getRequest().getHeader("Authorization");
        if (StringUtils.isEmpty(uuid)) {
            // 用户忘记传递（测试接口）
            return new AuthorizationDecision(false);
        }

        // 根据uuid从redis获取token
        String token = redisTemplate.opsForValue().get(RedisKeyConstants.LOGIN_USER_TOKEN+uuid);
        if (StringUtils.isEmpty(token)) {
            // UUID乱传
            // token自动过期，需要重新登陆
            // 用户忘记传递（测试接口）
            return new AuthorizationDecision(false);
        }

        // 解析token
        Claims claims = JwtUtil.parseJWT(secret, token);
        String userJson = (String) claims.get("user");

        // 获取token中存储的用户信息
        LoginUserDetails userDetails = JSONObject.parseObject(userJson, LoginUserDetails.class);

        // 和这次请求传递的uuid做比较
        // 第二个账号登陆会覆盖第一个账号在redis中的uuid，信息，所以uuid没有比较的需要

        // uuid续期
        redisTemplate.opsForValue().set(RedisKeyConstants.LOGIN_USER_UUID+userDetails.getUsername(), uuid, expire, TimeUnit.SECONDS);
        // token续期
        redisTemplate.opsForValue().set(RedisKeyConstants.LOGIN_USER_TOKEN+uuid, token, expire,TimeUnit.SECONDS);

        // 验证用户是否拥有该资源
        String method = request.getRequest().getMethod();
        String uri = request.getRequest().getRequestURI();  //  /nursingProject/save    GET /nursingProject/**
        uri = uri.replaceAll("/api", "");
        String resource = method + "" + uri;
        System.out.println("请求资源路径：--------------------------------"+resource);

        AntPathMatcher matcher = new AntPathMatcher();
        for (String r : userDetails.getResourceRequestPaths()) {
            if(matcher.match(r, resource)){
                System.out.println("有权限访问资源：" + resource+"--------------------"+r);
                return new AuthorizationDecision(true);
            }
        }
        return new AuthorizationDecision(false);
    }
}
